#ifndef CIF_DATA_LOADER_H
#define CIF_DATA_LOADER_H

#include <stdio.h>
#include "ACifDataLoader.h"

#define READ_BUFFER_MAX_LENGTH       1024
#define PATTERN_BUFFER_MAX_LENGTH    32

/**
 * The CifDataLoader class.
 * Loads file in CIF format.
 */
class CifDataLoader : public ACifDataLoader
{
private:

	/** 
     * An array of patterns.
     */
	char** patterns;
	
	/** 
     * A count of patterns.
     */
	int patternsCount;

	/** 
     * The current position of pattern matching.
     */
	int patternPos;

    /**
     * The complex data value symbol.
	 * Stores symbol used to represent the beginning of the value.
     */
	char complexDataSymbol;

    /**
     * The number of current pattern.
	 * Stores number of the pattern matches to current symbol.
     */
	int patternNumber;

	char *readBuffer;
	
	int readBufferLen;

	char *patternBuffer;

	int patternBufferLen;

	/**
	 * An opening character indicating the begin of a complex data value.
	 */
	char complexDataValueOpeningCharacter;

	/**
	 * A closing character indicating the end of a complex data value.
	 */
	char complexDataValueClosingCharacter;

	/**
     * Parses all data from input file.
     * @return CIF_ERROR_CODE_OK if the file was parsed successfully.
     */
	void Parse();

	/**
     * Checks if input character is whitespace or end of line symbol.
	 * @param c The character.
     * @return NotZero if the character is whitespace.
     */
	int IsWhitespace(char c);

	/**
     * Matches the character to the pattern.
	 * @param c The character.
     * @return NotZero if the character is whitespace.
     */
	int MatchPattern(char c);

	/**
     * Runs patterns action according to number of pattern.
	 * @param patternNo A number of a pattern.
     * @return CIF_ERROR_CODE_OK if there are no errors.
     */
	int RunPatternAction(int patternNo);

	/**
     * Parses data block.
     * @return CIF_ERROR_CODE_OK if there are no errors.
     */
	int DataBlockAction();

	/**
     * Reads data block code.
     * @return CIF_ERROR_CODE_OK if there are no errors.
     */
	int ReadDataBlockCode();

	/**
     * Parses data item.
     * @return CIF_ERROR_CODE_OK if there are no errors.
     */
	int DataItemAction();

	/**
     * Reads the name of a data item.
     * @return CIF_ERROR_CODE_OK if there are no errors.
     */
	int ReadDataItemName();

	/**
     * Reads the value of a data item.
     * @return CIF_ERROR_CODE_OK if there are no errors.
     */
	int ReadDataItemValue();

	/**
     * Parses loop.
     * @return CIF_ERROR_CODE_OK if there are no errors.
     */
	int LoopAction();

    /**
     * Skips current line.
     * @return CIF_ERROR_CODE_OK if there are no errors.
     */
	int SkipLine();

	/**
     * Moves current position of reading to the previous one.
     * @return CIF_ERROR_CODE_OK if there are no errors.
     */
	int StepBack();

	int StepBack(int stepsCount);

	/**
     * Skips whitespaces and comments.
     * @return CIF_ERROR_CODE_OK if there are no errors.
     */
	int SkipWhitespacesAndComments();

	int ReadLoopColumnNames();

	int ReadLoopRows();

	char ReadNextSymbol();

	int IsPatternMatched();

	int IsComplexDataValuePattern();

	/**
     * Reads complex data value.
     * @return Read data or NULL in case of error.
     */
	char *ReadComplexDataValue();

public:

    /**
     * The default constructor.
     * Initializes all members using default values.
     */
	CifDataLoader();

	/**
     * The destructor.
     * Frees all used memory.
     */
	~CifDataLoader();
};

#endif